# VUE Forms
# Forms Vue mastery
- -> encapsulate all forms into components.
- buld reusable components
- default for input is
text
if nothing is declared
2 way to get data from input:
- use
v-model
-> has 2-way binding - or
@input
-event-listener (might be good for validation)
# v-model
v-bind
, creates a one-way binding, from the data to the template.
v-model
is creating two-way data binding.
v-model is a combination of :value
and @input
<input type="text" :value="name" @input="setName"/>
- two-way data binding
<label>EMAIL</label>
<input type="email" required v-model="email" />
<label>Role:</label>
<select v-model="role">
<option value="developer">Web Developer</option>
<option value="designer">Web Designer</option>
</select>
# checkbox
<div class="terms">
<input type="checkbox" require v-model="terms" />
<label>Accept terms and conditions</label>
</div>
# multiple checkboxes with same v-model
- adds value to the array
<div>
<input type="checkbox" value="shaun" v-model="names" />
<label>Shaun</label>
</div>
<div>
<input type="checkbox" value="yoshi" v-model="names" />
<label>yoshi</label>
</div>
<div>
<input type="checkbox" value="mario" v-model="names" />
<label>mario</label>
</div>
# keyboard
-> access to event
<input type="text" v-model="tempSkill" @keyup="addSkill" />
//
methods: {
addSkill(event) {
console.log(event);
},
},
# v-model-Modifiers
# .number
v-model.number
is a modifier that typecasts the value as a number.
<input id="age" name="age" type="number" />
even with type="number"
, the value of HTML input elements always returns a string.
if you use a ref, no automaric type-conversion takes place
But with vue, this returns a number - with vue3:
<input v-model.number="age" type="number" />
-> forces a number
other modifiers:
# .lazy
- don't update immedialtely
# .trim
trims extra whitespace on beginning/end (like using the trim()
-function)
# Dropdowns
v-model
works on <select>
<div >
<label for="referrer">How did you hear about us?</label>
<select id="referrer" name="referrer" v-model="referrer">
<option value="google">Google</option>
<option value="wom">Word of mouth</option>
<option value="newspaper">Newspaper</option>
</select>
</div>
# Radio and Checkboxes
for a single checkbox
<input
type="checkbox"
id="confirm-terms"
name="confirm-terms"
v-model="confirm"
/>
-> you get true or false
add a
value
-attribute andv-model
to every checkboxuse an empty array for the data -> you get an array with the value of all the options
<div >
<h2>What are you interested in?</h2>
<div>
<input
id="interest-news"
name="interest"
type="checkbox"
v-model="interest"
value="News"
/>
<label for="interest-news">News</label>
</div>
<div>
<input
id="interest-tutorials"
name="interest"
type="checkbox"
v-model="interest"
value="Tutorials"
/>
<label for="interest-tutorials">Tutorials</label>
</div>
<div>
<input
id="interest-nothing"
name="interest"
type="checkbox"
v-model="interest"
value="Nothing"
/>
<label for="interest-nothing">Nothing</label>
</div>
</div>
# Form Validation
validate on
- submit method
- every keystroke
- wehenever an element looses focus ('blur')
@blur="validateInput"
<div class="form-control">
<label for="user-name">Your Name</label>
<input
id="user-name"
name="user-name"
type="text"
v-model.trim="userName"
@blur="validateInput"
/>
<p v-if="usernameValidity === 'invalid'">Please enter a valid name!</p>
</div>
...
validateInput() {
if (this.userName === '') {
this.usernameValidity = 'invalid';
} else {
this.usernameValidity = 'valid';
}
}
# Build Custom Element -
# Binding to the value
you can use v-model
on custom components. it uses a special prop "modelValue" and a special event "update:modelValue"
use props: ['modelValue'],
props: ['modelValue'],
emits: ['update:modelValue'],
in the custom element: eg.
# modelValue
By default in Vue 3, v-model
expects a property named modelValue
to be on your v-model-capable component.
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
return {
activeOption: this.modelValue
};
},
methods: {
activate(option) {
this.activeOption = option;
this.$emit('update:modelValue', option);
}
}
};
another example:
<template>
<label v-if="label">{{ label }}</label>
<input
:value="modelValue"
:placeholder="label"
class="field"
>
</template>
<script>
export default {
props: {
label: {
type: String,
default: ''
},
modelValue: {
type: [String, Number],
default: ''
}
}
}
</script>
# Emitting update:modelValue
All components that are capable of being v-modeled
have to emit an event in order for the parent to be able to catch the updates to that component’s data.
In Vue 3, by default all v-model
contracts expect for your component to emit an update:modelValue
event,
<input
:placeholder="label"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
# Passing $attrs
for: Attributes, classes & styles
when you pass down attributes, classes and styles from a parent to a child, Vue will attempt to automatically figure out where inside your template these attributes should be injected.
In single root components (components with a single wrapping element), Vue will inject all the attributes, classes and styles into the root element.
In multi-root components, Vue can’t figure out which one of the nodes, or fragments, it should inject the attributes to.
-> you have to manually bind the
$attrs
object to the element.
<input
v-bind="$attrs"
class="field"
:placeholder="label"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>